home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pp / pp-6.0 / Chans / grey / ppp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-18  |  21.4 KB  |  948 lines

  1. /* ppp.c: ppp interface routines */
  2.  
  3. # ifndef lint
  4. static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Chans/grey/RCS/ppp.c,v 6.0 1991/12/18 20:10:19 jpo Rel $";
  5. # endif
  6.  
  7. /*
  8.  * $Header: /xtel/pp/pp-beta/Chans/grey/RCS/ppp.c,v 6.0 1991/12/18 20:10:19 jpo Rel $
  9.  *
  10.  * $Log: ppp.c,v $
  11.  * Revision 6.0  1991/12/18  20:10:19  jpo
  12.  * Release 6.0
  13.  *
  14.  */
  15.  
  16.  
  17.  
  18. #include "util.h"
  19. #include "ppp.h"
  20. #include "qmgr.h"
  21. #include "prm.h"
  22. #include "q.h"
  23. #include "adr.h"
  24. #include "chan.h"
  25. #include <varargs.h>
  26. #include "retcode.h"
  27. #include "dr.h"
  28. #include "ap.h"
  29.  
  30. static int ppp_sd = NOTOK;
  31. static CHAN *mychan;
  32. static struct prm_vars prm;
  33. static Q_struct Qs;
  34. static ADDR *ad_sender, *ad_recip, *ad_list;
  35. static enum { jnthdr, initialise, go } state;
  36. static char *this_msg;
  37. static int naddrs = 0;
  38. static char *cur_host;
  39. static char *cur_net;
  40. static char *jnt_host;
  41. static int rox_id;
  42. static int ppp_error_status;
  43. static int data_bytes;
  44. static struct timeval data_timer;
  45. #if PP_DEBUG > PP_DEBUG_NONE
  46. static int ppp_debug = 0;
  47. static int debug_init (), debug_nextmsg ();
  48. static void pdeliverystatus (), pindividualdeliverystatus ();
  49. #endif
  50.  
  51. static int ppp_initfnx (), ppp_procfnx ();
  52. static void ppp_lose ();
  53. static int ros_indication (), ros_work (), ros_result (),
  54.     error (), ureject ();
  55. static void ros_advise (), acs_advise ();
  56. static void cleanup_everything ();
  57. static char *bigendian ();
  58. static char *mk_jnt ();
  59. static int assemble_jntheader ();
  60. static int fetch_data ();
  61. static int ppp_procfnx_aux ();
  62.  
  63. static int lastop = NOTOK;
  64. #define INITOP    1
  65. #define PROCOP    2
  66. extern struct RyOperation table_Qmgr_Operations[];
  67. extern char *quedfldir;
  68.  
  69. int ppp_init (argc, argv)
  70. int    argc;
  71. char    **argv;
  72. {
  73.     struct AcSAPstart   acss;
  74.     register struct AcSAPstart *acs = &acss;
  75.     struct AcSAPindication  acis;
  76.     register struct AcSAPindication *aci = &acis;
  77.     register struct AcSAPabort   *aca = &aci -> aci_abort;
  78.         struct RoSAPindication  rois;
  79.         register struct RoSAPindication *roi = &rois;
  80.         register struct RoSAPpreject   *rop = &roi -> roi_preject;
  81.     register struct PSAPstart *ps = &acs -> acs_start;
  82.     int    result;
  83.  
  84.     chan_init (argv[0]);
  85.     (void) chdir (quedfldir);
  86. #if PP_DEBUG > PP_DEBUG_NONE
  87.     for (result = 0; result < argc; result ++)
  88.         if (strcmp (argv[result], "debug") == 0)
  89.             return debug_init ();
  90. #endif
  91.     if (RyDispatch (NOTOK, table_Qmgr_Operations,
  92.             operation_Qmgr_channelInitialise, ppp_initfnx,
  93.             roi) == NOTOK) {
  94.         ros_advise (rop, "RyDispatch: channelInitialise");
  95.         return NOTOK;
  96.     }
  97.     if (RyDispatch (NOTOK, table_Qmgr_Operations,
  98.             operation_Qmgr_processmessage, ppp_procfnx,
  99.             roi) == NOTOK) {
  100.         ros_advise (rop, "RyDispatch: processmessage");
  101.         return NOTOK;
  102.     }
  103.  
  104.     if (AcInit (argc, argv, acs, aci) == NOTOK) {
  105.         acs_advise (aca, "AcInit");
  106.         return NOTOK;
  107.     }
  108.  
  109.     PP_DBG (("A-ASSOCIATE.INDICATION: <%d, %s, %s, %s, %d>",
  110.          acs -> acs_sd, sprintoid (acs -> acs_context),
  111.          sprintaei (&acs -> acs_callingtitle),
  112.          sprintaei (&acs -> acs_calledtitle), acs -> acs_ninfo));
  113.     ppp_sd = acs -> acs_sd;
  114.  
  115.     result = AcAssocResponse (ppp_sd, ACS_ACCEPT, ACS_USER_NULL,
  116.                   NULLOID, NULLAEI, NULLPA, NULLPC,
  117.                   ps -> ps_defctxresult,
  118.                   ps -> ps_prequirements,
  119.                   ps -> ps_srequirements, SERIAL_NONE,
  120.                   ps -> ps_settings, &ps -> ps_connect,
  121.                   NULLPEP, 0, aci);
  122.     ACSFREE (acs);
  123.     if (result == NOTOK) {
  124.         acs_advise (aca, "A-ASSOCIATE.RESPONSE");
  125.         return ppp_sd = NOTOK;
  126.     }
  127.     if (RoSetService (ppp_sd, RoPService, roi) == NOTOK) {
  128.         ros_advise (rop, "set RO/PS fails");
  129.         ppp_lose ();
  130.         return NOTOK;
  131.     }
  132.  
  133.     /* try and get the init channel op */
  134.     if (ros_work (ppp_sd, INITOP) != OK) {
  135.         ppp_lose ();
  136.         return NOTOK;
  137.     }
  138.     return OK;
  139. }
  140.  
  141.  
  142. int ppp_getnextmessage (host, net)
  143. char    **host;
  144. char    **net;
  145. {
  146.     int    result;
  147.  
  148.     state = jnthdr;
  149. #if PP_DEBUG > PP_DEBUG_NONE
  150.     if (ppp_debug)
  151.         result = debug_nextmsg ();
  152.     else
  153. #endif
  154.     result = ros_work (ppp_sd, PROCOP);
  155.     switch (result) {
  156.         default:
  157.         case NOTOK:
  158.         ros_result (ppp_sd, deliverystate, rox_id);
  159.         ppp_lose ();
  160.         return NOTOK;
  161.  
  162.         case OK:
  163.         if (ppp_error_status == NOTOK) {
  164.             ros_result (ppp_sd, deliverystate, rox_id);
  165.             return ppp_getnextmessage (host, net);
  166.         }
  167.         if (jnt_host)
  168.             free (jnt_host);
  169.         *host = jnt_host = mk_jnt(cur_host);
  170.         if (jnt_host == NULLCP)
  171.             return NOTOK;
  172.         if (cur_net)
  173.             free (cur_net);
  174.         if (mychan -> ch_out_info == NULLCP) {
  175.             PP_OPER (NULLCP, ("Channel %s has no info string",
  176.                       mychan -> ch_name));
  177.             return NOTOK;
  178.         }
  179.         *net = cur_net = strdup (mychan -> ch_out_info);
  180.         return OK;
  181.  
  182.         case DONE:
  183.         return DONE;
  184.     }
  185. }
  186.  
  187. static char    *hdrbuf;
  188.  
  189. int ppp_getdata (buf, len)
  190. char    **buf;
  191. int    *len;
  192. {
  193.     if (hdrbuf) {
  194.         free (hdrbuf);
  195.         hdrbuf = NULLCP;
  196.     }
  197.  
  198.     switch (state) {
  199.         case jnthdr:
  200.         data_bytes = 0;
  201.         timer_start (&data_timer);
  202.         state = initialise;
  203.         return assemble_jntheader (buf, len);
  204.  
  205.         case initialise:
  206.         case go:
  207.         return fetch_data (buf, len);
  208.  
  209.         default:
  210.         PP_LOG (LLOG_EXCEPTIONS, ("Bad state in getdata"));
  211.         return NOTOK;
  212.     }
  213. }
  214.  
  215. static int assemble_jntheader (buf, lengthp)
  216. char **buf;
  217. int *lengthp;
  218. {
  219.     ADDR    *ap;
  220.     char    *str;
  221.     int    len = 0;
  222.  
  223.     PP_NOTICE (("Originator %s", ad_sender -> ad_r822adr));
  224.     for (ap = ad_list; ap; ap = ap -> ad_next) {
  225.         if ((str = bigendian (ap -> ad_r822adr)) == NULLCP)
  226.             return NOTOK;
  227.         if (hdrbuf == NULL) {
  228.             hdrbuf = smalloc (len = strlen (str) + 2 + 1);
  229.             (void) strcpy (hdrbuf, str);
  230.             (void) strcat (hdrbuf, ap -> ad_next ? ",\n" : "\n\n");
  231.         }
  232.         else {
  233.             hdrbuf = realloc (hdrbuf, len += strlen (str) + 2);
  234.             (void) strcat (hdrbuf, str);
  235.             (void) strcat (hdrbuf, ap -> ad_next ? ",\n" : "\n\n");
  236.         }
  237.     }
  238.     *buf = hdrbuf;
  239.     *lengthp = len - 1;
  240.     data_bytes += len - 1;
  241.     return OK;
  242. }
  243.  
  244. static char transbuf[BUFSIZ];
  245. static char    *formatdir;
  246.  
  247. static int fetch_data (buf, lengthp)
  248. char    **buf;
  249. int    *lengthp;
  250. {
  251.     char filename[BUFSIZ];
  252.     static FILE *fp;
  253.     static int first;
  254.     int    n;
  255.  
  256.     *buf = "";
  257.     *lengthp = 0;
  258.  
  259.     if (state == initialise) {
  260.         state = go;
  261.         first = 1;
  262.  
  263.         if (qid2dir (this_msg, ad_list, TRUE, &formatdir) == NOTOK)
  264.             return NOTOK;
  265.         if (msg_rinit (formatdir) != RP_OK)
  266.             return NOTOK;
  267.         if (msg_rfile (filename) != RP_OK) {
  268.             msg_rend ();
  269.             return NOTOK;
  270.         }
  271.         if ((fp = fopen (filename, "r")) == NULL) {
  272.             msg_rend ();
  273.             return NOTOK;
  274.         }
  275.     }
  276.  
  277.     if (!feof(fp) && (n = fread (transbuf, 1, sizeof transbuf, fp)) > 0) {
  278.         *buf = transbuf;
  279.         *lengthp = n;
  280.         data_bytes += n;
  281.         return OK;
  282.     }
  283.     if (first) {
  284.         first = 0;
  285.         (void) strcpy (transbuf, "\n");
  286.         *buf = transbuf;
  287.         *lengthp = 1;
  288.         data_bytes += 1;
  289.         return OK;
  290.     }
  291.     
  292.     if (ferror (fp)) {
  293.         msg_rend ();
  294.         (void) fclose (fp);
  295.         return NOTOK;
  296.     }
  297.     (void) fclose (fp);
  298.     
  299.         
  300.     if ((n = msg_rfile (filename)) == RP_DONE){
  301.         msg_rend ();
  302.         *lengthp = 0;
  303.         return DONE;
  304.     }
  305.  
  306.     if (rp_isbad (n)) {
  307.         msg_rend ();
  308.         return NOTOK;
  309.     }
  310.  
  311.     if ((fp = fopen (filename, "r")) == NULL) {
  312.         msg_rend ();
  313.         return NOTOK;
  314.     }
  315.  
  316.     return fetch_data (buf, lengthp);
  317. }
  318.  
  319. int ppp_status (status, reason)
  320. int    status;
  321. char    *reason;
  322. {
  323.     ADDR    *ap;
  324.     char    buf[BUFSIZ];
  325.     int    confrep = int_Qmgr_status_positiveDR;
  326.     int    drrep = int_Qmgr_status_negativeDR;
  327.  
  328.     if (status == PPP_STATUS_DONE)
  329.         timer_end (&data_timer, data_bytes, "Data Transfered");
  330.  
  331.     for (ap = ad_list; ap; ap = ap -> ad_next) {
  332.         if (ap -> ad_resp == 0)
  333.             continue;
  334.         switch (status) {
  335.             case PPP_STATUS_DONE:
  336.             if (ap ->ad_usrreq == AD_USR_CONFIRM ||
  337.                 ap -> ad_mtarreq == AD_MTA_CONFIRM ||
  338.                 ap -> ad_mtarreq == AD_MTA_AUDIT_CONFIRM) {
  339.                 (void) sprintf (buf, "Successfully sent to %s for recipient %s",
  340.                         cur_host, ap -> ad_r822adr);
  341.                 set_1dr (&Qs, ap -> ad_no, this_msg,
  342.                      DRR_NO_REASON,
  343.                      -1, buf);
  344.                 delivery_set (ap -> ad_no, confrep);
  345.                 confrep = int_Qmgr_status_successSharedDR;
  346.             }
  347.             else {
  348.                 (void) wr_ad_status (ap, AD_STAT_DONE);
  349.                 (void) wr_stat (ap, &Qs, this_msg, data_bytes);
  350.                 delivery_set (ap -> ad_no,
  351.                           int_Qmgr_status_success);
  352.             }
  353.             PP_NOTICE ((">>> Message %s transfered to %s on %s", 
  354.                     this_msg, ap -> ad_r822adr, cur_host));
  355.             break;
  356.  
  357.             case PPP_STATUS_CONNECT_FAILED:
  358.             delivery_setstate (ap -> ad_no,
  359.                        int_Qmgr_status_mtaFailure,
  360.                        reason);
  361.             PP_NOTICE (("Connection to %s failed [%s]",
  362.                     cur_host, reason ? reason : ""));
  363.             break;
  364.  
  365.             case PPP_STATUS_PERMANENT_FAILURE:
  366.             (void) sprintf (buf, 
  367.     "Blue book transfer to %s failed (permanent error code): \"%s\"",
  368.                     cur_host, reason);
  369.             delivery_set (ap -> ad_no,
  370.                       drrep);
  371.             drrep = int_Qmgr_status_failureSharedDR;
  372.             set_1dr (&Qs, ap -> ad_no, this_msg,
  373.                  DRR_TRANSFER_FAILURE,
  374.                  DRD_UNRECOGNISED_OR, buf);
  375.             PP_NOTICE (("Transfer to %s for %s perm failed [%s]",
  376.                     cur_host, this_msg, buf));
  377.             break;
  378.  
  379.             case PPP_STATUS_TRANSIENT_FAILURE:
  380.             delivery_setstate (ap -> ad_no,
  381.                        int_Qmgr_status_messageFailure,
  382.                        reason);
  383.             PP_NOTICE (("Temporary failure for %s to %s [%s]",
  384.                     this_msg, cur_host, reason ? reason : ""));
  385.             break;
  386.         }
  387.     }
  388.     if (rp_isbad(wr_q2dr (&Qs, this_msg))) {
  389.         PP_LOG (LLOG_EXCEPTIONS,
  390.                ("%s wr_q2dr failure",mychan->ch_name));
  391.         (void) delivery_resetDRs (int_Qmgr_status_messageFailure);
  392.     }
  393.  
  394.     cleanup_everything ();
  395.     rd_end ();
  396. #if PP_DEBUG > PP_DEBUG_NONE
  397.     if (ppp_debug){
  398.          pdeliverystatus (deliverystate);
  399.          return OK;
  400.      }
  401.     else
  402. #endif
  403.         return ros_result (ppp_sd, deliverystate, rox_id);
  404. }
  405.  
  406. void ppp_terminate ()
  407. {
  408.     if (ppp_sd != NOTOK)
  409.         ppp_lose ();
  410. }
  411.  
  412. static void ppp_lose ()
  413. {
  414.     struct AcSAPindication  acis;
  415.     struct RoSAPindication  rois;
  416.     register struct RoSAPindication *roi = &rois;
  417.  
  418.     (void) AcUAbortRequest (ppp_sd, NULLPEP, 0, &acis);
  419.     (void) RyLose (ppp_sd, roi);
  420.     ppp_sd = NOTOK;
  421. }
  422.  
  423. static int ppp_initfnx (sd, ryo, rox, in, roi)
  424. int    sd;
  425. struct RyOperation *ryo;
  426. struct RoSAPinvoke *rox;
  427. caddr_t in;
  428. struct RoSAPindication *roi;
  429. {
  430.     char    *p;
  431.  
  432.         if (rox -> rox_nolinked == 0) {
  433.                 PP_LOG (LLOG_EXCEPTIONS,
  434.                         ("RO-INVOKE.INDICATION/%d: %s, unknown linkage %d",
  435.                         sd, ryo -> ryo_name, rox -> rox_linkid));
  436.                 return ureject (sd, ROS_IP_LINKED, rox, roi);
  437.         }
  438.         PP_DBG (("RO-INVOKE.INDICATION/%d: %s", sd, ryo -> ryo_name));
  439.  
  440.     p = qb2str ((struct type_Qmgr_Channel *) in);
  441.  
  442.     if ((mychan = ch_nm2struct (p)) == NULLCHAN) {
  443.         PP_LOG (LLOG_EXCEPTIONS, ("Unknown channel %s", p));
  444.         free (p);
  445.         error (sd, error_Qmgr_protocol, (caddr_t) NULL, rox -> rox_id);
  446.         return NOTOK;
  447.     }
  448.     PP_NOTICE (("Starting %s (%s)", mychan -> ch_name, mychan -> ch_show));
  449.     rename_log (mychan -> ch_name);
  450.  
  451.     free (p);
  452.  
  453.     if (RyDsResult (sd, rox -> rox_id, (caddr_t) NULL,
  454.             ROS_NOPRIO, roi) == NOTOK) {
  455.         ros_advise (&roi -> roi_preject, "RESULT");
  456.         return NOTOK;
  457.     }
  458.     
  459.     lastop = INITOP;
  460.     return OK;
  461. }
  462.  
  463. static int ppp_procfnx (sd, ryo, rox, in, roi)
  464. int    sd;
  465. struct RyOperation *ryo;
  466. struct RoSAPinvoke *rox;
  467. caddr_t in;
  468. struct RoSAPindication *roi;
  469. {
  470.     struct type_Qmgr_ProcMsg *arg = (struct type_Qmgr_ProcMsg *)in;
  471.  
  472.         if (rox -> rox_nolinked == 0) {
  473.                 PP_LOG (LLOG_EXCEPTIONS,
  474.                         ("RO-INVOKE.INDICATION/%d: %s, unknown linkage %d",
  475.                         sd, ryo -> ryo_name, rox -> rox_linkid));
  476.                 return ureject (sd, ROS_IP_LINKED, rox, roi);
  477.         }
  478.         PP_DBG (("RO-INVOKE.INDICATION/%d: %s", sd, ryo -> ryo_name));
  479.  
  480.     rox_id = rox -> rox_id;
  481.     lastop = PROCOP;
  482.     return ppp_procfnx_aux (arg);
  483. }
  484.  
  485. static int ppp_procfnx_aux (arg)
  486. struct type_Qmgr_ProcMsg *arg;
  487. {
  488.     struct type_Qmgr_UserList *up;
  489.     int    retval;
  490.     int    ad_count = 0;
  491.     ADDR    *ap, *alp = NULL;
  492.  
  493.     delivery_init (arg -> users);
  494.  
  495.     if (this_msg)
  496.         free (this_msg);
  497.     this_msg = qb2str (arg -> qid);
  498.  
  499.     ad_sender = NULLADDR;
  500.  
  501.     if (ad_recip) {
  502.         q_free (&Qs);
  503.         prm_free (&prm);
  504.     }
  505.     ad_recip = NULLADDR;
  506.  
  507.     retval = rd_msg (this_msg, &prm, &Qs, &ad_sender, &ad_recip, &ad_count);
  508.     if (rp_isbad (retval)) {
  509.         PP_LOG (LLOG_EXCEPTIONS, ("local/rd_msg err: %s", this_msg));
  510.         return NOTOK;
  511.     }
  512.  
  513.     naddrs = 0;
  514.     ad_list = NULLADDR;
  515.     ppp_error_status = OK;
  516.     for (ap = ad_recip; ap; ap = ap -> ad_next) {
  517.                 for (up = arg ->users; up; up = up -> next) {
  518.                         if (up -> RecipientId -> parm != ap -> ad_no)
  519.                                 continue;
  520.  
  521.                         switch (chan_acheck (ap, mychan, ad_list == NULLADDR, 
  522.                         &cur_host)) {
  523.                 case OK:
  524.                     break;
  525.  
  526.                 default:
  527.                     continue;
  528.             }
  529.             break;
  530.                 }
  531.                 if (up == NULL)
  532.                         continue;
  533.  
  534.                 if (ad_list == NULLADDR)
  535.                         ad_list = alp = (ADDR *) calloc (1, sizeof *alp);
  536.                 else {
  537.                         alp -> ad_next = (ADDR *) calloc (1, sizeof *alp);
  538.                         alp = alp -> ad_next;
  539.                 }
  540.                 *alp = *ap;
  541.                 alp -> ad_next = NULLADDR;
  542.         naddrs ++;
  543.         }
  544.  
  545.     if (ad_list == NULLADDR) {
  546.         PP_LOG (LLOG_EXCEPTIONS, ("No recipients in user list"));
  547.         rd_end ();
  548.         ppp_error_status = NOTOK;
  549.         return OK;
  550.     }
  551.     PP_NOTICE (("Processing msg %s to %s", this_msg, cur_host));
  552.     return OK;
  553. }
  554.  
  555.  
  556. static int  ros_work (fd, what)
  557. int     fd;
  558. int    what;
  559. {
  560.     int     result;
  561.     caddr_t out;
  562.     struct RoSAPindication  rois;
  563.     register struct RoSAPindication *roi = &rois;
  564.     register struct RoSAPpreject   *rop = &roi -> roi_preject;
  565.     fd_set rfds;
  566.  
  567.     for (;;) {
  568.         PP_TRACE (("ros_work loop (%d, %d)", fd, what));
  569.         FD_ZERO (&rfds);
  570.         FD_SET (fd, &rfds);
  571.         xselect (fd + 1, &rfds, NULLFD, NULLFD, NOTOK);
  572.         switch (result = RyWait (fd, NULLIP, &out, OK, roi)) {
  573.             case NOTOK: 
  574.             if (rop -> rop_reason == ROS_TIMER)
  575.                 break;
  576.             case OK: 
  577.             case DONE: 
  578.             if ((result = ros_indication (fd, roi)) != OK)
  579.                 return result;
  580.             break;
  581.  
  582.             default: 
  583.             PP_LOG (LLOG_EXCEPTIONS,
  584.                 ("unknown return from RoWaitRequest=%d",
  585.                  result));
  586.             return NOTOK;
  587.         }
  588.         break;
  589.     }
  590.     if (lastop == what)
  591.         return OK;
  592.     return NOTOK;
  593. }
  594.  
  595. /*   */
  596.  
  597. static int ros_indication (sd, roi)
  598. int     sd;
  599. register struct RoSAPindication *roi;
  600. {
  601.     int     reply,
  602.         result;
  603.  
  604.     switch (roi -> roi_type) {
  605.         case ROI_INVOKE: 
  606.         case ROI_RESULT: 
  607.         case ROI_ERROR: 
  608.         PP_LOG (LLOG_EXCEPTIONS,
  609.             ("unexpected indication type=%d", roi -> roi_type));
  610.         return NOTOK;
  611.  
  612.         case ROI_UREJECT: 
  613.         {
  614.             register struct RoSAPureject   *rou =
  615.                 &roi -> roi_ureject;
  616.  
  617.             if (rou -> rou_noid)
  618.                 PP_LOG (LLOG_EXCEPTIONS,
  619.                     ("RO-REJECT-U.INDICATION/%d: %s",
  620.                      sd, RoErrString (rou -> rou_reason)));
  621.             else
  622.                 PP_LOG (LLOG_EXCEPTIONS, 
  623.                     ("RO-REJECT-U.INDICATION/%d: %s (id=%d)",
  624.                      sd, RoErrString (rou -> rou_reason),
  625.                      rou -> rou_id));
  626.             return NOTOK;
  627.         }
  628.  
  629.         case ROI_PREJECT: 
  630.         {
  631.             register struct RoSAPpreject   *rop =
  632.                 &roi -> roi_preject;
  633.  
  634.             ros_advise (rop, "RO-REJECT-P.INDICATION");
  635.             return NOTOK;
  636.         }
  637.  
  638.         case ROI_FINISH: 
  639.         {
  640.             register struct AcSAPfinish *acf = &roi -> roi_finish;
  641.             struct AcSAPindication  acis;
  642.             register struct AcSAPabort *aca = &acis.aci_abort;
  643.  
  644.             PP_TRACE (("A-RELEASE.INDICATION/%d: %d",
  645.                    sd, acf -> acf_reason));
  646.  
  647.             result = AcRelResponse (sd, reply = ACS_ACCEPT,
  648.                         ACR_NORMAL, NULLPEP, 0, &acis);
  649.  
  650.             ACFFREE (acf);
  651.  
  652.             if (result == NOTOK)
  653.                 acs_advise (aca, "A-RELEASE.RESPONSE");
  654.             else
  655.                 if (reply != ACS_ACCEPT)
  656.                     break;
  657.  
  658.             return DONE;
  659.         }
  660.         /* NOTREACHED */
  661.  
  662.         default: 
  663.         PP_LOG (LLOG_EXCEPTIONS,
  664.             ("unknown indication type=%d", roi -> roi_type));
  665.         return NOTOK;
  666.     }
  667.     return OK;
  668. }
  669.  
  670. static int ros_result (sd, val, id)
  671. int     sd;
  672. struct type_Qmgr_DeliveryStatus *val;
  673. int    id;
  674. {
  675.     struct RoSAPindication rois;
  676.     struct RoSAPindication *roi = &rois;
  677.  
  678.     if (val == NULL)
  679.         return error (sd, error_Qmgr_congested, (caddr_t) NULL,
  680.                   id);
  681.  
  682.     if (RyDsResult (sd, id, (caddr_t) val, ROS_NOPRIO, roi)
  683.             == NOTOK) {
  684.         ros_advise (&roi -> roi_preject, "RESULT");
  685.         return NOTOK;
  686.     }
  687.     return OK;
  688. }
  689.  
  690. /*     ERRORS */
  691.  
  692. static void    ros_advise (rop, event)
  693. register struct RoSAPpreject *rop;
  694. char   *event;
  695. {
  696.     char    buffer[BUFSIZ];
  697.  
  698.     if (rop -> rop_cc > 0)
  699.     (void) sprintf (buffer, "[%s] %*.*s", RoErrString (rop -> rop_reason),
  700.         rop -> rop_cc, rop -> rop_cc, rop -> rop_data);
  701.     else
  702.     (void) sprintf (buffer, "[%s]", RoErrString (rop -> rop_reason));
  703.  
  704.     PP_LOG (LLOG_EXCEPTIONS, ("%s: %s", event, buffer));
  705.     if (ROS_FATAL (rop -> rop_reason))
  706.         exit (1);
  707. }
  708.  
  709. /*   */
  710.  
  711. static void    acs_advise (aca, event)
  712. register struct AcSAPabort *aca;
  713. char   *event;
  714. {
  715.     char    buffer[BUFSIZ];
  716.  
  717.     if (aca -> aca_cc > 0)
  718.     (void) sprintf (buffer, "[%s] %*.*s",
  719.         AcErrString (aca -> aca_reason),
  720.         aca -> aca_cc, aca -> aca_cc, aca -> aca_data);
  721.     else
  722.     (void) sprintf (buffer, "[%s]", AcErrString (aca -> aca_reason));
  723.  
  724.     PP_LOG (LLOG_EXCEPTIONS, ("%s: %s (source %d)", event, buffer,
  725.         aca -> aca_source));
  726. }
  727.  
  728. /*     ERROR */
  729.  
  730. static int  error (sd, err, param, id)
  731. int     sd,
  732.     err;
  733. caddr_t param;
  734. int    id;
  735. {
  736.     struct RoSAPindication rois;
  737.     struct RoSAPindication *roi = &rois;
  738.  
  739.     if (RyDsError (sd, id, err, param, ROS_NOPRIO, roi) == NOTOK) {
  740.         ros_advise (&roi -> roi_preject, "ERROR");
  741.         return NOTOK;
  742.     }
  743.  
  744.     return OK;
  745. }
  746.  
  747. static int  ureject (sd, reason, rox, roi)
  748. int     sd,
  749.     reason;
  750. struct RoSAPinvoke *rox;
  751. struct RoSAPindication *roi;
  752. {
  753.     if (RyDsUReject (sd, rox -> rox_id, reason, ROS_NOPRIO, roi) == NOTOK) {
  754.         ros_advise (&roi -> roi_preject, "U-REJECT");
  755.         return NOTOK;
  756.     }
  757.  
  758.     return OK;
  759. }
  760.  
  761. static char *bigendian (addr)
  762. char    *addr;
  763. {
  764.     extern int ap_outtype;
  765.     static char     *newaddr = NULLCP;
  766.     AP_ptr          tree = NULLAP,
  767.             group = NULLAP,
  768.             name = NULLAP,
  769.             local = NULLAP,
  770.             domain = NULLAP,
  771.             route = NULLAP;
  772.  
  773.     if (newaddr) {
  774.         free (newaddr);
  775.         newaddr = NULLCP;
  776.     }
  777.  
  778.  
  779.     ap_outtype = AP_PARSE_733 | AP_PARSE_BIG;
  780.  
  781.  
  782.     if (ap_s2p  (addr, &tree, &group, &name, &local, &domain, &route)
  783.         == (char *)NOTOK) {
  784.         PP_LOG (LLOG_EXCEPTIONS,
  785.             ("Unable to parse (s2p) Recipient addr %s", addr));
  786.         return NULLCP;
  787.     }
  788.  
  789.  
  790.     if ((newaddr = ap_p2s (group, name, local, domain, route))
  791.         == (char *)NOTOK) {
  792.         PP_LOG (LLOG_EXCEPTIONS,
  793.             ("Unable to parse (p2s) Recipient addr %s", addr));
  794.         newaddr = NULLCP;
  795.     }
  796.  
  797.     ap_free (tree);
  798.  
  799.     PP_NOTICE (("Recipient Address '%s'",  newaddr));
  800.     return newaddr;
  801. }
  802.  
  803. #if PP_DEBUG > PP_DEBUG_NONE
  804. static int debug_init ()
  805. {
  806.     char    buf[BUFSIZ], *p;
  807.  
  808.     fprintf (stderr, "Running in debug mode\nInput channel name: ");
  809.     ppp_debug = 1;
  810.     (void) fflush (stderr);
  811.  
  812.     if (fgets (buf, sizeof buf, stdin) == NULL)
  813.         return NOTOK;
  814.     if ((p = index (buf, '\n')) != NULLCP)
  815.         *p = '\0';
  816.     if ((mychan = ch_nm2struct (buf)) == NULLCHAN) {
  817.         PP_LOG (LLOG_EXCEPTIONS, ("Unknown channel %s", p));
  818.         return NOTOK;
  819.     }
  820.     return OK;
  821. }    
  822.  
  823. static int debug_nextmsg ()
  824. {
  825.     char     buf[BUFSIZ], *p;
  826.     int    num;
  827.     struct type_Qmgr_ProcMsg *arg;
  828.     struct type_Qmgr_UserList *temp, *tail = NULL;
  829.  
  830.     fprintf (stderr, "Input message name: ");
  831.     (void) fflush (stderr);
  832.  
  833.     if (fgets (buf, sizeof buf, stdin) == NULL)
  834.         return NOTOK;
  835.     if ((p = index (buf, '\n')) != NULLCP)
  836.         *p = '\0';
  837.     arg = (struct type_Qmgr_ProcMsg *) calloc (1, sizeof *arg);
  838.     arg -> qid = str2qb (buf, strlen (buf), 1);
  839.     arg -> channel = str2qb (mychan -> ch_name, 
  840.                 strlen (mychan -> ch_name), 1);
  841.     fprintf (stderr, "Input recipients terminated by -1: ");
  842.     fflush (stderr);
  843.  
  844.     do {
  845.         scanf ("%d", &num);
  846.         if (num != -1) {
  847.             temp = (struct type_Qmgr_UserList *)
  848.                 calloc (1, sizeof *temp);
  849.             temp -> RecipientId = (struct type_Qmgr_RecipientId *)
  850.                 calloc (1, sizeof *temp->RecipientId);
  851.             temp -> RecipientId -> parm = num;
  852.             if (arg -> users) {
  853.                 tail -> next = temp;
  854.                 tail = temp;
  855.             }
  856.             else
  857.                 arg -> users = tail = temp;
  858.         }
  859.     } while (num != -1);
  860.     while ((num = getchar()) != EOF && num != '\n')
  861.         continue;
  862.     return ppp_procfnx_aux (arg);
  863. }
  864.  
  865. static void pdeliverystatus (status)
  866. struct type_Qmgr_DeliveryStatus *status;
  867. {
  868.         fprintf (stderr, "Delivery status\n");
  869.         if (status == NULL)
  870.                 fprintf (stderr, "Complete failure\n");
  871.         else {
  872.                 struct type_Qmgr_DeliveryStatus *ix = status;
  873.                 while (ix != NULL)
  874.                 {
  875.                         pindividualdeliverystatus(ix->IndividualDeliveryStatus);
  876.                         ix = ix->next;
  877.                 }
  878.         }
  879. }
  880.  
  881. static void pindividualdeliverystatus(status)
  882. struct type_Qmgr_IndividualDeliveryStatus *status;
  883. {
  884.         fprintf (stderr, "Recipient %d: ", status->recipient->parm);
  885.  
  886.         switch (status->status) {
  887.             case int_Qmgr_status_success:
  888.                 fprintf (stderr, "success");
  889.                 break;
  890.             case int_Qmgr_status_successSharedDR:
  891.                 fprintf (stderr, "successSharedDR");
  892.                 break;
  893.             case int_Qmgr_status_failureSharedDR:
  894.                 fprintf (stderr, "failureSharedDR");
  895.                 break;
  896.             case int_Qmgr_status_negativeDR:
  897.                 fprintf (stderr, "negativeDR");
  898.                 break;
  899.             case int_Qmgr_status_positiveDR:
  900.                 fprintf (stderr, "positiveDR");
  901.                 break;
  902.             case int_Qmgr_status_messageFailure:
  903.                 fprintf (stderr, "message failure");
  904.                 break;
  905.             case int_Qmgr_status_mtaFailure:
  906.                 fprintf (stderr, "mta failure");
  907.                 break;
  908.             case int_Qmgr_status_mtaAndMessageFailure:
  909.                 fprintf (stderr, "mta and message failure");
  910.                 break;
  911.             default:
  912.                 fprintf (stderr, "unknown");
  913.                 break;
  914.         }
  915.         putc ('\n', stderr);
  916. }
  917.  
  918. #endif
  919.  
  920. static void cleanup_everything ()
  921. {
  922.     if (hdrbuf != NULL) {
  923.         free (hdrbuf);
  924.         hdrbuf = NULL;
  925.     }
  926.     lastop = NOTOK;
  927. }
  928.  
  929. static char    *mk_jnt (str)
  930. char    *str;
  931. {
  932.     char    buf1[BUFSIZ], buf2[BUFSIZ];
  933.     char    *argv[30];
  934.     int    argc;
  935.  
  936.     strcpy (buf1, str);
  937.     argc = sstr2arg (buf1, 30, argv, ".");
  938.     
  939.     if (argc < 1)
  940.         return NULLCP;
  941.     strcpy (buf2, argv[--argc]);
  942.     while (--argc >= 0) {
  943.         strcat (buf2, ".");
  944.         strcat (buf2, argv[argc]);
  945.     }
  946.     return strdup (buf2);
  947. }
  948.